package com.example.demo.controller;

import com.example.demo.enums.EventEnum;
import com.example.demo.enums.MsgTypeEnum;
import com.example.demo.utils.CheckUtil;
import com.example.demo.utils.WxMpXmlMessage;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

@RequestMapping("wechat")
@RestController
@Slf4j
public class WechatController {

  public static HashMap<String, String> map = new HashMap<>();
 
  /*
   * @param signature 微信加密签名，signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。
   * @param timestamp 时间戳
   * @param nonce     这是个随机数
   * @param echostr   随机字符串，验证成功后原样返回UserController
   */
  @GetMapping
  public void get(@RequestParam(required = false) String signature,
                  @RequestParam(required = false) String timestamp,
                  @RequestParam(required = false) String nonce,
                  @RequestParam(required = false) String echostr,
                  HttpServletResponse response) throws IOException {
    if (!CheckUtil.checkSignature(signature, timestamp, nonce)) {
      log.warn("接收到了未通过校验的微信消息，这可能是token配置错了，或是接收了非微信官方的请求");
      return;
    }

    try (PrintWriter out = response.getWriter()) {
      out.write(echostr);
    }
  }


  /**
   * 当设置完微信公众号的接口后，微信会把用户发送的消息，扫码事件等推送过来
   *
   * @param signature 微信加密签名，signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。
   * @param encType 加密类型（暂未启用加密消息）
   * @param msgSignature 加密的消息
   * @param timestamp 时间戳
   * @param nonce 随机数
   * @throws IOException
   */
  @PostMapping(produces = "text/xml; charset=UTF-8")
  public void post(HttpServletRequest request,
                  HttpServletResponse response,
                  @RequestBody String requestBody,
                  @RequestParam("signature") String signature,
                  @RequestParam(name = "encrypt_type", required = false) String encType,
                  @RequestParam(name = "msg_signature", required = false) String msgSignature,
                  @RequestParam("timestamp") String timestamp,
                  @RequestParam("nonce") String nonce) throws IOException {
    if (!CheckUtil.checkSignature(signature, timestamp, nonce)) {
      log.warn("接收到了未通过校验的微信消息，这可能是token配置错了，或是接收了非微信官方的请求");
      return;
    }

    log.info("接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
            + " timestamp=[{}], nonce=[{}], requestBody=[\\n{}\\n]",
            signature, encType, msgSignature, timestamp, nonce, requestBody);

    WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
    log.info("inMessage：{}", inMessage);

    MsgTypeEnum msgTypeEnum = MsgTypeEnum.getByName(inMessage.getMsgType());
    switch (msgTypeEnum) {
      case text:
        log.info("收到文本类型消息：{}", inMessage);
      case event:
        handleEvent(inMessage);
      default:
        log.info("跳过该消息类型：{}", inMessage.getMsgType());

    }
  }

  private void handleEvent(WxMpXmlMessage inMessage) {
    EventEnum eventEnum = EventEnum.valueOf(inMessage.getEvent());

    switch (eventEnum) {
      case subscribe:
        log.info("收到event-subscribe类型消息：{}", inMessage);
        if (StringUtils.hasLength(inMessage.getTicket())) {
          map.put(inMessage.getTicket(), inMessage.getFromUser());
        }
      case unsubscribe:
        log.info("收到event-unsubscribe类型消息：{}", inMessage);
      case SCAN:
        log.info("收到event-SCAN类型消息：{}", inMessage);
        map.put(inMessage.getTicket(), inMessage.getFromUser());
      default:
        log.info("跳过该event类型：{}", inMessage.getEvent());

    }
  }
}